#include "verifyextraunitydlg.h"
#include "ui_verifyextraunitydlg.h"

#include "utils.h"

#include <QSqlQuery>

VerifyExtraUnityDlg::VerifyExtraUnityDlg(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::VerifyExtraUnityDlg)
{
    ui->setupUi(this);
    init();
}

VerifyExtraUnityDlg::~VerifyExtraUnityDlg()
{
    delete ui;
}

/**
 * @brief 科目选择改变，调整可选择的币种
 * @param index
 */
void VerifyExtraUnityDlg::subSelChanged(int index)
{
    int fid = ui->cmbSelSub->itemData(index).toInt();
    bool useWb = false;
    if(fid != 0){
        QSqlQuery q;
        QString s = QString("select isReqDet from firSubjects where id=%1").arg(fid);
        if(!q.exec(s))
            return;
        if(q.first())
            useWb = q.value(0).toBool();
    }
    else{
        ui->btnRead->setEnabled(false);
        ui->btnUpdate->setEnabled(false);
        ui->btnPreview->setEnabled(false);
    }
    if(useWb && ui->cmbMt->count()==1)
        ui->cmbMt->addItem(tr("美元"),USD);
    else if(!useWb && ui->cmbMt->count()==2)
        ui->cmbMt->removeItem(1);
}

void VerifyExtraUnityDlg::init()
{
    QSqlQuery q;
    QString s = "select id,subName from firSubjects where isView=1 order by subCode";
    if(!q.exec(s))
        return;
    ui->tview->setColumnWidth(0,40);
    ui->cmbMt->addItem(tr("人民币"),RMB);
    ui->cmbSelSub->addItem(tr("所有"),0);
    while(q.next()){
        int id = q.value(0).toInt();
        QString name= q.value(1).toString();
        ui->cmbSelSub->addItem(name,id);
    }
    ui->tview->addAction(ui->actInspectOmitSSub);

    ui->tvValues->setColumnWidth(0,50);
    ui->tvUpdates->setColumnWidth(0,50);
    ui->tvUpdates->setColumnWidth(1,50);
    ui->tvUpdates->setColumnWidth(2,50);
    ui->tvUpdates->setColumnWidth(3,50);
    ui->tvUpdates->setColumnWidth(4,80);
    ui->tvUpdates->setColumnWidth(5,50);
    ui->tvUpdates->setColumnWidth(6,80);
    ui->tvUpdates->setColumnWidth(7,50);
    ui->tvUpdates->setHidden(true);

    connect(ui->cmbSelSub,SIGNAL(currentIndexChanged(int)),this,SLOT(subSelChanged(int)));
    connect(ui->tview,SIGNAL(itemSelectionChanged()),this,SLOT(rowSelectChanged()));
}

/**
 * @brief 是否还有需要进行补齐操作的科目
 */
bool VerifyExtraUnityDlg::hasFillRow()
{
    if(ui->tvValues->rowCount() == 0)
        return false;
    for(int i = 0; i < ui->tvValues->rowCount(); ++i){
        QPushButton* btn = qobject_cast<QPushButton*>(ui->tvValues->cellWidget(i,CI_BUTTON));
        if(btn)
            return true;
    }
    return false;
}

/**
 * @brief 检查主目余额与子目汇总余额是否一致
 */
void VerifyExtraUnityDlg::on_pushButton_clicked()
{
    ui->pushButton->setEnabled(false);
    QApplication::processEvents();
    ui->tview->setRowCount(0);
    ui->tvValues->setRowCount(0);
    QList<int>ids;
    int mt = ui->cmbMt->itemData(ui->cmbMt->currentIndex()).toInt();
    ui->edtMtName->setText(mt==RMB?tr("人民币"):tr("美元"));
    if(ui->cmbSelSub->count() == 1)
        return;
    if(ui->cmbSelSub->currentIndex() == 0){
        for(int i = 1; i < ui->cmbSelSub->count(); ++i)
            ids<<ui->cmbSelSub->itemData(i).toInt();
    }
    else
        ids<<ui->cmbSelSub->itemData(ui->cmbSelSub->currentIndex()).toInt();
    foreach(int fid, ids){
        bool ok = true;
        QStringList errors;
        if(!BusiUtil::verifyExtraUnityForFSub(fid,ok,errors,ui->spnY->value(),ui->spnM->value(),mt)){
            QMessageBox::critical(this,"",tr("执行出错！"));
            return;
        }
        if(!ok){
            foreach (QString str, errors) {
                QStringList l = str.split(" ");
                int r = ui->tview->rowCount();
                ui->tview->insertRow(r);
                for(int i = 0; i < l.count(); ++i){
                    QTableWidgetItem* item = new QTableWidgetItem(l.at(1));
                    item->setData(Qt::UserRole,mt);
                    ui->tview->setItem(r,0,item);//id
                    ui->tview->setItem(r,1,new QTableWidgetItem(l.at(2)));//科目名
                    ui->tview->setItem(r,2,new QTableWidgetItem(l.at(3)));//年
                    ui->tview->setItem(r,3,new QTableWidgetItem(l.at(4)));//月
                    ui->tview->setItem(r,4,new QTableWidgetItem(l.at(5)));//主目余额
                    ui->tview->setItem(r,5,new QTableWidgetItem(l.at(6)));//主目方向
                    ui->tview->setItem(r,6,new QTableWidgetItem(l.at(7)));//子目汇总值
                    ui->tview->setItem(r,7,new QTableWidgetItem(l.at(8)));//差值
                }
            }
            ui->tview->setCurrentCell(0,0);
            on_actInspectOmitSSub_triggered();
        }
    }
    ui->pushButton->setEnabled(true);
}

/**
 * @问题子目表的行选择改变，主要是为了识别选择的行对应的时间范围
 * 可以选择两个行，且这两行之间（包括选择的行）对对应到同一个子目，这样才可以启用读取原值按钮
 */
void VerifyExtraUnityDlg::rowSelectChanged()
{
    QList<QTableWidgetSelectionRange> range = ui->tview->selectedRanges();
    if(range.count() != 2){
        ui->btnRead->setEnabled(false);
        ui->btnPreview->setEnabled(false);
        return;
    }
    int sr = range.at(0).topRow();
    int er = range.at(1).bottomRow();
    int y = ui->tview->item(sr,2)->text().toInt();
    int m = ui->tview->item(sr,3)->text().toInt();
    ui->deStart->setDate(QDate(y,m,1));
    y = ui->tview->item(er,2)->text().toInt();
    m = m = ui->tview->item(er,3)->text().toInt();
    ui->deEnd->setDate(QDate(y,m,1));
    if(ui->tvValues->currentRow() != -1){
        ui->btnRead->setEnabled(true);
        //ui->btnPreview->setEnabled(true);
    }
}

/**
 * @brief 填补指定年月缺失的子目余额
 */
void VerifyExtraUnityDlg::fillValue()
{
    int row = -1;
    for(int i = 0; i < ui->tvValues->rowCount(); ++i){
        QPushButton* btn = qobject_cast<QPushButton*>(ui->tvValues->cellWidget(i,CI_BUTTON));
        if(btn && btn == sender()){
            row = i;
            break;
        }
    }
    if(row != -1){
        QTableWidgetItem* item = ui->tvValues->item(row,0);
        int sid = item->text().toInt();
        int seid = item->data(Qt::UserRole).toInt();
        Double v = Double(ui->tvValues->item(row,CI_NEW_V)->text().toDouble());
        int dir = ui->tvValues->item(row,CI_NEW_D)->text().toInt();
        QSqlQuery q;
        QString s = QString("update detailExtras set value=%1,dir=%2 where seid=%3 and fsid=%4")
                .arg(v.toString2()).arg(dir).arg(seid).arg(sid);
        if(!q.exec(s))
            return;
        int num = q.numRowsAffected();
        if(num != 1 && dir != DIR_P){
            s = QString("insert into detailExtras(seid,fsid,value,dir) values(%1,%2,%3,%4)")
                    .arg(seid).arg(sid).arg(v.toString2()).arg(dir);
            if(!q.exec(s))
                return;
        }
        ui->tvValues->setCellWidget(row,CI_BUTTON,0);
        if(!hasFillRow()){
            ui->tview->removeRow(ui->tview->currentRow());
            ui->tvValues->setRowCount(0);
            if(ui->tview->rowCount()>0){
                ui->tview->setCurrentCell(0,0);
                on_actInspectOmitSSub_triggered();
            }
        }
    }
}

/**
 * @brief 检测指定月份遗漏的子目余额
 */
void VerifyExtraUnityDlg::on_actInspectOmitSSub_triggered()
{
    ui->tvValues->setRowCount(0);
    int r = ui->tview->currentRow();
    if(r==-1)
        return;
    int fid,y,m,mt;
    fid = ui->tview->item(r,0)->text().toInt();
    mt = ui->tview->item(r,0)->data(Qt::UserRole).toInt();
    y = ui->tview->item(r,2)->text().toInt();
    m = ui->tview->item(r,3)->text().toInt();
    int yy,mm;
    if(m == 1){
        yy = y-1;
        mm = 12;
    }
    else{
        yy=y;
        mm = m -1;
    }

    QSqlQuery q;
    QString s = QString("select id from FSAgent where fid=%1").arg(fid);
    if(!q.exec(s))
        return;
    QList<int> sids;
    while(q.next())
        sids<<q.value(0).toInt();

    //1、读取上一月份的当前主目下子目余额并建立子目余额值表
    QHash<int, Double> prevs;
    QHash<int,int> preDirs;
    s = QString("select id from subjectExtras where year=%1 and month=%2 and mt=%3")
            .arg(yy).arg(mm).arg(mt);
    //QString s2 = QString("select id from subjectExtraDirs where year=%1 and month=%2 and mt=%3")
    //        .arg(yy).arg(mm).arg(mt);

    if(!q.exec(s) || !q.first())
        return;
    int seid = q.value(0).toInt();
    s = QString("select fsid,value,dir from detailExtras where seid=%1").arg(seid);
    if(!q.exec(s))
        return;
    while(q.next()){
        int sid = q.value(0).toInt();
        if(!sids.contains(sid))
            continue;
        prevs[sid] = Double(q.value(1).toDouble());
        preDirs[sid] = q.value(2).toInt();
    }
    //2、读取当月分录，计算本期发生后的余额（只关注当前主目的分录）
    QDate d(y,m,1);
    QString ds=d.toString(Qt::ISODate);
    ds.chop(3);
    s = QString("select BusiActions.secSubId,BusiActions.jMoney,BusiActions.dMoney,BusiActions.dir from BusiActions join PingZhengs on "
                "BusiActions.pid=PingZhengs.id where (PingZhengs.date like '%1%') and"
                " PingZhengs.isForward != 33 and PingZhengs.isForward != 32 and PingZhengs.isForward != 31 and"
                " BusiActions.firSubId=%2 and BusiActions.moneyType=%3 and BusiActions.dir!=0")
            .arg(ds).arg(fid).arg(mt);
    if(!q.exec(s))
        return;
    while(q.next()){
        int sid = q.value(0).toInt();
        int dir = q.value(3).toInt();
        Double v;
        if(dir == DIR_J)
            v = Double(q.value(1).toDouble());
        else
            v = Double(q.value(2).toDouble());
        if(!prevs.contains(sid)){
            prevs[sid] = v;
            preDirs[sid] = dir;
        }
        else{
            if(preDirs.value(sid) != dir)
                v.changeSign();
            prevs[sid] += v;
        }
    }
    //3、根据计算后的余额项，逐项检测在明细余额表中是否存在对应值项，如存在，且相等则从值表中删除，不断重复
    //读取保存当前月份子目余额的指针
    s = QString("select id from subjectExtras where year=%1 and month=%2 and mt=%3")
            .arg(y).arg(m).arg(mt);
    if(!q.exec(s) || !q.first())
        return;
    seid = q.value(0).toInt();
    QHashIterator<int,Double> it(prevs);
    int row = -1;
    while(it.hasNext()){
        it.next();
        if(it.value() == 0)
            preDirs[it.key()] = DIR_P;
        s = QString("select id,value,dir from detailExtras where seid=%1 and fsid=%2")
                .arg(seid).arg(it.key());
        if(!q.exec(s))
            return;
        int old_d = DIR_P; Double old_v;
        int eid = -1;
        if(q.first()){
            eid = q.value(0).toInt();
            old_d = q.value(2).toInt();
            old_v = Double(q.value(1).toDouble());
        }
        int new_d = preDirs.value(it.key());
        Double new_v = it.value();
        if(new_d == DIR_P && old_d == DIR_P){
            prevs.remove(it.key());
            preDirs.remove(it.key());
        }
        else if(new_v == old_v && new_d == old_d){
            prevs.remove(it.key());
            preDirs.remove(it.key());
        }
        else{
            if((new_d + old_d) == 0){
                Double tem = new_v;
                tem.changeSign();
                if(tem == old_v){
                    prevs.remove(it.key());
                    preDirs.remove(it.key());
                    continue;
                }
            }
            row++;
            ui->tvValues->insertRow(row);
            QTableWidgetItem* item = new QTableWidgetItem(QString::number(it.key()));
            item->setData(Qt::UserRole,seid);
            ui->tvValues->setItem(row,CI_ID,item);
            //读取子目名
            s = QString("select SecSubjects.subName from FSAgent join SecSubjects on "
                        "FSAgent.sid=SecSubjects.id where FSAgent.id=%1").arg(it.key());
            if(!q.exec(s))
                return;
            q.first();
            QString name = q.value(0).toString();
            ui->tvValues->setItem(row,CI_NAME,new QTableWidgetItem(name));
            ui->tvValues->setItem(row,CI_OLD_V,new QTableWidgetItem(old_v.toString2()));
            ui->tvValues->setItem(row,CI_OLD_D,new QTableWidgetItem(QString::number(old_d)));
            ui->tvValues->setItem(row,CI_NEW_V,new QTableWidgetItem(new_v.toString2()));
            ui->tvValues->setItem(row,CI_NEW_D,new QTableWidgetItem(QString::number(new_d)));
            QPushButton* btn = new QPushButton(tr("补齐"),this);
            connect(btn,SIGNAL(clicked()),this,SLOT(fillValue()));
            ui->tvValues->setCellWidget(row,CI_BUTTON,btn);
        }
    }
}

/**
 * @读取指定子目在指定时间范围内的余额值项
 */
void VerifyExtraUnityDlg::on_btnRead_clicked()
{
    ui->tvUpdates->setRowCount(0);
    int sid = ui->tvValues->item(ui->tvValues->currentRow(),0)->text().toInt();
    int sy = ui->deStart->date().year();
    int sm = ui->deStart->date().month();
    int ey = ui->deEnd->date().year();
    int em = ui->deEnd->date().month();
    int mt = ui->edtMtName->text()==tr("人民币")?1:2;
    QString s;
    if(sy==ey)
        s = QString("select id from subjectExtras where mt=%1 and year=%2 and "
                    "month>=%3 and month<=%4 order by year,month")
                .arg(mt).arg(sy).arg(sm).arg(em);
    else
        s = QString("select id from subjectExtras where mt=%1 and (year>%2 and "
                    "year<%3 or year=%2 and month>=%4 or year=%3 and month<=%5) "
                    "order by year,month")
                .arg(mt).arg(sy).arg(ey).arg(sm).arg(em);

    //"select id from subjectExtras where mt=1 and year=2012 and month>=10 and month<=12 order by year,month"
    //"select id from subjectExtras where mt=1 and (year>2012 and year<2014 or year=2012 and month>=10 or year=2014 and month<=2) order by year,month"

    QSqlQuery q;
    if(!q.exec(s))
        return;
    QList<int> seids;
    while(q.next())
        seids<<q.value(0).toInt();
    //填写读取到的原值
    s = QString("select id,value,dir from detailExtras where seid=:seid and fsid=%1").arg(sid);
    if(!q.prepare(s))
        return;
    int y=sy,m=sm;
    for(int i = 0; i < seids.count(); ++i){
        int seid = seids.at(i);
        q.bindValue(":seid",seid);
        if(!q.exec())
            return;
        int id = q.value(0).toInt();
        int dir = q.value(2).toInt();
        Double v = Double(q.value(1).toDouble());
        ui->tvUpdates->insertRow(i);
        ui->tvUpdates->setItem(i,0,new QTableWidgetItem(id!=0?QString::number(id):""));
        ui->tvUpdates->setItem(i,1,new QTableWidgetItem(QString::number(seid)));
        ui->tvUpdates->setItem(i,2,new QTableWidgetItem(QString::number(y)));
        ui->tvUpdates->setItem(i,3,new QTableWidgetItem(QString::number(m)));
        ui->tvUpdates->setItem(i,4,new QTableWidgetItem(v.toString()));
        ui->tvUpdates->setItem(i,5,new QTableWidgetItem(QString::number(dir)));
        m++;
        if(m>12){
            y++;
            m=1;
        }
    }
    ui->btnPreview->setEnabled(true);
}

void VerifyExtraUnityDlg::on_btnUpdate_clicked()
{
    QMessageBox::warning(this,"",tr("预览更新后的结果将"));

}

void VerifyExtraUnityDlg::on_btnPreview_clicked()
{
    int row = ui->tvValues->currentRow();
    if(row == -1)
        return;
    Double deltaV = Double(ui->tvValues->item(row,2)->text().toDouble());
    for(int i = 0; i < ui->tvUpdates->rowCount(); ++i){
        Double v = Double(ui->tvUpdates->item(i,4)->text().toDouble());
        int dir = ui->tvUpdates->item(i,5)->text().toInt();
        Double nv; int nd;
        if(dir == DIR_D){
            v.changeSign();
            nv = v + deltaV;
            if(nv == 0)
                nd = DIR_P;
            else if(nv > 0)
                nd = DIR_J;
            else{
                nv.changeSign();
                nd = DIR_D;
            }
        }
        else{
            nv = v + deltaV;
            nd = DIR_J;
        }

        QTableWidgetItem* item = ui->tvUpdates->item(i,6);
        if(!item){
            item = new QTableWidgetItem;
            ui->tvUpdates->setItem(i,6,item);
        }
        item->setText(nv.toString());
        item = ui->tvUpdates->item(i,7);
        if(!item){
            item = new QTableWidgetItem;
            ui->tvUpdates->setItem(i,7,item);
        }
        item->setText(QString::number(nd));
    }

}
